﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using IEx.Common;
using IEx.Common.Sources;
using IEx.Model.Partials;

namespace IEx.Model
{
    public interface IRepository
    {
        long InsertAttachment(Attachment attachment);

        bool DeleteAttachment(long attachmentId);

        List<Attachment> GetPressreleaseAttachments(long PressreleaseID, int LanguageID);

        long InsertPressreleases(Announcement announement);

        long UpdatePressrelease(Announcement announcement);

        MessageType GetMessageType(SourceIds sourceID, string messageTypeName, string messageTypeGroup = null);

        List<Attachment> GetAttachmentForPrMissingContent(string sourceCode, Nullable<int> lang, DateTime fromDate, DateTime toDate);

        void UpdatePressreleasesContent(long pressleaseId, string content);

        DateTime GetLastestDateAnnouncement(string sourceCode, int sourceId, int langId);
    }
    public class Repository : IRepository
    {
        private string conectionString = ConfigurationManager.ConnectionStrings["DataFeedConnectionString"].ConnectionString;

        public long InsertAttachment(Attachment attachment)
        {
            using (Database db = new Database(conectionString))
            {
                try
                {

                    return (long)db.ExcuteScalarQuery("spAttachmentInsert",
                        attachment.MediaBinary,
                        attachment.MineType,
                        attachment.PressreleaseId,
                        attachment.FileName,
                        attachment.Location,
                        attachment.DisplayOrder,
                        attachment.LanguageId,
                        attachment.IsBlob);
                }
                catch (Exception ex)
                {
                    Logger.WriteError("Insert Attachment Error:", ex);
                    return 0;
                }
            }
        }

        public bool DeleteAttachment(long attachmentId)
        {
            using (Database db = new Database(conectionString))
            {
                return db.ExecuteQuery("spAttachmentDelete", attachmentId) > 0;
            }
        }

        public List<Attachment> GetPressreleaseAttachments(long pressreleaseId, int langId)
        {
            using (Database db = new Database(conectionString))
            {
                IEnumerable<Attachment> attachments = db.GetManyRecords<Attachment>("spAttachmentSelectByPressreleaseId", pressreleaseId, langId);
                if (attachments != null)
                    return attachments.ToList();
            }

            return new List<Attachment>();
        }

        public long InsertPressreleases(Announcement announcement)
        {
            using (Database db = new Database(conectionString))
            {
                try
                {
                    if (string.IsNullOrEmpty(announcement.Title) || announcement.DateNumberic <= 0
                        || announcement.SourceId <= 0 || string.IsNullOrEmpty(announcement.SourceCode)
                        || announcement.LangId <= 0)
                    {
                        throw new Exception("Pressrelease does not match the insertion condition");
                    }

                    return (long)db.ExcuteScalarQuery("spPressreleasesInsertIfNotExist",
                            announcement.DateTime,
                            announcement.DateNumberic,
                            announcement.SourceCode,
                            announcement.LangId,
                            announcement.Message,
                            announcement.Title,
                            announcement.Attachment,
                            announcement.SourceId,
                            announcement.MessageTypeId);
                }
                catch (Exception ex)
                {
                    Logger.WriteError("DB ERROR:", ex);
                    return -1;
                }
            }
        }

        public long UpdatePressrelease(Announcement announcement)
        {
            using (Database db = new Database(conectionString))
            {
                return (long)db.ExcuteScalarQuery("spPressreleasesUpdateMessageAndTypeId",
                    announcement.DateTime,
                    announcement.DateNumberic,
                    announcement.SourceCode,
                    announcement.LangId,
                    announcement.Message,
                    announcement.Title,
                    announcement.SourceId,
                    announcement.MessageTypeId);
            }
        }

        public MessageType GetMessageType(SourceIds sourceId, string messageTypeName, string messageTypeGroup = null)
        {
            // Transaction might be deadlocked when App runs into multi-thread.
            // By using Deadlock retry policy we should retry action when transaction is deadlocked.
            // Is there any better solution?
            // http://blog.sqlauthority.com/2007/05/16/sql-server-fix-error-1205-transaction-process-id-was-deadlocked-on-resources-with-another-process-and-has-been-chosen-as-the-deadlock-victim-rerun-the-transaction/
            using (Database db = new Database(conectionString))
            {
                return (new SqlRetryPolicy()).ExecuteAction<MessageType>(() => db.GetSingleRecord<MessageType>("spMessageTypeSelectAndInsertIfNotExist", sourceId, messageTypeName, messageTypeGroup));
            }
        }

        public List<Attachment> GetAttachmentForPrMissingContent(string sourceCode, int? lang, DateTime fromDate, DateTime toDate)
        {
            using (Database DB = new Database(conectionString))
            {
                return DB.GetManyRecords<Attachment>("spAttachmentSelectByCompanyCodeAndPeriod", sourceCode, lang, fromDate, toDate).ToList();
            }
        }

        public void UpdatePressreleasesContent(long pressleaseId, string content)
        {
            using (Database DB = new Database(conectionString))
            {
                DB.ExecuteQuery("spPressreleasesUpdateMessage", pressleaseId, content);
            }
        }

        public DateTime GetLastestDateAnnouncement(string sourceCode, int sourceId, int langId)
        {
            using (Database db = new Database(conectionString))
            {
                Nullable<DateTime> result = db.GetSingleRecord<Nullable<DateTime>>("spPressreleasesSelectLatestDate", sourceCode, sourceId, langId);
                if (result == null)
                    return new DateTime(1999, 1, 1);
                else
                    return DateTime.Parse(result.ToString());
            }
        }
    }
}
